<?php
/***************************************************************
*  Copyright notice
*
*  (c) 2009 Thomas Breuss <thomas.breuss@zephir.ch>
*  All rights reserved
*
*  This script is part of the TYPO3 project. The TYPO3 project is
*  free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  The GNU General Public License can be found at
*  http://www.gnu.org/copyleft/gpl.html.
*
*  This script is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/

require_once(PATH_tslib.'class.tslib_pibase.php');

/**
 * Plugin 'Filelinks' for the 'filelinks' extension.
 *
 * @author	Thomas Breuss <thomas.breuss@zephir.ch>
 * @package	TYPO3
 * @subpackage	tx_filelinks
 */
class tx_filelinks_pi1 extends tslib_pibase
{
    public $prefixId      = 'tx_filelinks_pi1';		// Same as class name
    public $scriptRelPath = 'pi1/class.tx_filelinks_pi1.php';	// Path to this script relative to the extension dir.
    public $extKey        = 'filelinks';	// The extension key.
    public $pi_checkCHash = true;

    /**
     * @var string
     */
    private $iconPath;

    /**
     * @var string
     */
    private $imageWidth;

    /**
     * @var string
     */
    private $scriptPath;

    /**
     * @var boolean
     */
    private static $cssRendered = false;

    /**
     * @var boolean
     */
    private $forcedl = false;

    /**
     * @var boolean
     */
    private $secure = false;

    /**
     * @var boolean
     */
    private $fileinfo = false;

    /**
     * @var integer
     */
    private $cid;

    /**
     * @var array
     */
    private $rows;

    /**
     * @var string
     */
    private $uploadFolder = 'uploads/tx_filelinks/';


    /**
     * @param string $content
     * @param array $conf
     * @return string
     */
	public function main($content, $conf)
	{
		$this->conf = $conf;

		$this->pi_setPiVarDefaults();
        $this->pi_initPIflexForm();
        $this->pi_loadLL();

        $this->init();

        $filelinkUid = $this->getParam('download');
        
        if(($this->getParam('cid') == $this->cid) && ($filelinkUid !== null)) {
            $content .= $this->downloadAction($filelinkUid);
        }

        $content .= $this->defaultAction();

        return $this->pi_wrapInBaseClass($content);
    }
    
    /**
     * Initializer
     */
    protected function init()
    {

        // Alternativer Pfad zu View Skripten und Helfern
        $this->scriptPath = realpath($this->getExtConfValue('scriptPath'));

        $iconPath = trim($this->getExtConfValue('iconPath'));
        $this->iconPath = is_dir($iconPath) ? $iconPath : t3lib_extMgm::siteRelPath('cms') . 'tslib/media/fileicons/';

        $imageWidth = trim($this->getExtConfValue('imageWidth'));
        $this->imageWidth = empty($imageWidth) ? '' : $imageWidth;

        $this->forcedl = (bool)$this->getExtConfValue('forcedl');
        $this->fileinfo = (bool)$this->getExtConfValue('fileinfo');
        $this->secure = (bool)$this->getExtConfValue('secure');

        $this->cid = intval($this->cObj->data['uid']);
        
        $this->loadData();
    }

    /**
     * @return void
     */
    protected function loadData()
    {
        $this->rows = array();
        if(!empty($this->cObj->data['tx_filelinks'])) {
            $where = 'parentid='.(int)$this->getLocalizedUid();
            $where .= $GLOBALS['TSFE']->cObj->enableFields('tx_filelinks');
            $this->rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
               '*',
               'tx_filelinks',
               $where,
               '', // group by
               'sorting'
            );
        }
        $rowCount = count($this->rows);
        $this->firstId = empty($rowCount) ? 0 : $this->rows[0]['uid'];
        $this->lastId = empty($rowCount) ? 0 : $this->rows[$rowCount-1]['uid'];
    }

    /**
     * Default Action
     * 
     * @return string
     */
    public function defaultAction()
    {
        // CSS nur einmal rendern
        if(!self::$cssRendered) {
            $inlineCss = $this->render('styles', array('imageWidth'=>$this->imageWidth), 'css');
            $cssTempFile = TSpagegen::inline2TempFile($inlineCss,'css');
            $GLOBALS['TSFE']->additionalHeaderData[$this->prefixId] .= '<link rel="stylesheet" type="text/css" href="'.$cssTempFile.'" media="all" />';
            self::$cssRendered = true;
        }
        return $this->render('default');
    }

    /**
     * @param integer $filelinkUid
     * @return string
     */
    public function downloadAction($filelinkUid)
    {
        if($this->cid<1) {
            return $this->render('error');
        }

        if($this->cid !== intval($this->cObj->data['uid'])) {
            return $this->render('error');
        }

        foreach($this->rows AS $row) {
            if($row['uid'] == $filelinkUid) {

                if($row['link_type'] != 2) {
                    return $this->render('error');
                }

                // Löscht den Ausgabe-Puffer und deaktiviert die Ausgabe-Pufferung
                ob_end_clean();

                $filepath = urldecode($row['link_file']);                
                
                // Get mimetype
                $mimetype = $this->forcedl ? 'application/force-download' : $this->getMimeType($filepath);

                // Start sending headers
                header('Pragma: public'); // required
                header('Expires: 0');
                header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
                header('Cache-Control: private', false); // required for certain browsers
                header('Content-Transfer-Encoding: binary');
                header('Content-Type: ' . $mimetype);
                header('Content-Length: ' . filesize($filepath));
                header('Content-Disposition: attachment; filename="' . urldecode(basename($filepath)) . '";' );

                // Send data
                readfile($filepath);
                exit;

            }
        }

        return $this->render('error');
    }

    /**
     * @param string $filepath
     * @return string
     */
    protected function getMimeType($filepath)
    {
        $mimetype = '';

        // 1st choice: finfo_file
        if (function_exists('finfo_file')) {
            $finfo = finfo_open(FILEINFO_MIME);
            $mimetype = finfo_file($finfo, $filepath);
            finfo_close($finfo);
        }

        // 2nd choice: mime_content_type
        if ($mimetype == '' && function_exists('mime_content_type')) {
            $mimetype = mime_content_type($filepath);
        }

        // 3rd choice: Use external list of mimetypes
        if ($mimetype == '') {
            require_once(t3lib_extMgm::extPath('filelinks').'mimetypes.php');
            $defaultmimetype = 'application/octet-stream';
            $info = pathinfo($filepath);
            $extension = $info['extension'];
            $mimetype = isset($mimetypes[$extension]) ? $mimetypes[$extension] : $defaultmimetype;
        }

        return $mimetype;
    }

    /**
     * Siehe tslib_pibase::pi_wrapInBaseClass()
     *
     * @param string $str
     * @return string
     */
    public function pi_wrapInBaseClass($str)
    {
        $content = '<div class="'.str_replace('_','-',$this->prefixId).' layout-' . $this->cObj->data['layout'] . '">
		'.$str.'
	</div>
	';
        return $content;
    }

    /**
     * @global array $TYPO3_CONF_VARS
     * @param string $fieldName
     * @return mixed
     */
	protected function getExtConfValue($fieldName)
	{
		global $TYPO3_CONF_VARS;
		if(isset($TYPO3_CONF_VARS['EXT']['extConf'][$this->extKey])) {
			$extConf = @unserialize($TYPO3_CONF_VARS['EXT']['extConf'][$this->extKey]);
			if(array_key_exists($fieldName, $extConf)) {
				return $extConf[$fieldName];
			}
		}
		return null;
	}

    /**
     * Render template files
     *
     * @param string $template Name of the template file
     * @param array $variables Array of alle variables to set availalbe in the template. Key = name; Value = content
     * @param string $extension
     * @return string The content
     */
    protected function render($template, $variables = array(), $extension='php')
    {
        // Alternative script path
        if(!empty($this->scriptPath)) {
            $viewPath = $this->scriptPath;
            $viewScript = $viewPath . '/'. $template .'.'.$extension;
        }
        // Plugin script path
        if(empty($viewScript) || !file_exists($viewScript)) {
            $viewPath = dirname(__FILE__) . '/views';
            $viewScript = $viewPath . '/'. $template .'.'.$extension;
        }
        if(file_exists($viewScript)) {
            if(count($variables) > 0) {
                extract($variables, EXTR_SKIP);
            }
            ob_start();
            include $viewScript;
            $contents = ob_get_contents();
            ob_end_clean();
            return $contents;
        } else {
            throw new Exception($viewScript . ' does not exist');
        }
    }

    /**
     * Gets a parameter from piVars.  If the
     * parameter does not exist, NULL will be returned.
     *
     * If the parameter does not exist and $default is set, then
     * $default will be returned instead of NULL.
     *
     * @param string $paramName
     * @param mixed $default
     * @return mixed
     */
    protected function getParam($paramName, $default = null)
    {
        $value = isset($this->piVars[$paramName]) ? $this->piVars[$paramName] : null;
        if ((null == $value) && (null !== $default)) {
            $value = $default;
        }
        return $value;
    }

    /**
     * @param string $str
     * @return string
     */
    protected function escape($str)
    {
        return htmlentities($str, ENT_COMPAT, 'ISO-8859-1', false);
    }

	/**
	 * @param string $path
	 * @param integer|string $width
	 * @param integer|string $height
	 * @param string $type
	 * @return array
	 */
	protected function imageInfo($path, $width=0, $height=0, $type='')
    {
		$imgObj = t3lib_div::makeInstance('t3lib_stdGraphic');
		$imgObj->init();
		$imgObj->mayScaleUp = 0;
		$imageInfo = $imgObj->getImageDimensions($path);
    	if(is_array($imageInfo)) {
			$scaledImageInfo = $imgObj->imageMagickConvert($path, $type, $width, $height, '', '', '', 1);
			if(is_array($scaledImageInfo)) {
				// Source and scaled image have identical dimensions
				if($scaledImageInfo[0] === $imageInfo[0]) {
					if($scaledImageInfo[1] === $imageInfo[1]) {
						$scaledImageInfo = $imageInfo;
					}
				}
				return $scaledImageInfo;
			} else {
                trigger_error('ImageMagick is not installed', E_USER_NOTICE);
        		if(!empty($width) && !empty($height)) {
            		$imageInfo[0] = intval($width);
            		$imageInfo[1] = 0;
        		} elseif(!empty($width)) {
            		$imageInfo[0] = intval($width);
            		$imageInfo[1] = 0;
        		} elseif(!empty($height)) {
            		$imageInfo[0] = 0;
            		$imageInfo[1] = intval($height);
        		}
                return $imageInfo;
			}
		}
		return array();
	}    

    /**
     * @param array $row
     * @return string
     */
    protected function getImageLink(array $row)
    {
        if(($image=$this->getThumbnail($row))!='') {
            $imageInfo = $this->imageInfo($image, $this->imageWidth, 0);
            $image = "<img src=\"{$imageInfo[3]}\" width=\"{$imageInfo[0]}\" height=\"{$imageInfo[1]}\" alt=\"{$this->getLabel($row)}\" />";
        } elseif(($icon=$this->getIcon($row))!='') {
            $image = "<img src=\"{$icon}\" alt=\"{$this->getExtension($icon)}\" />";
        }
        $params = $this->getTypolinkParams($row);
        return $this->cObj->getTypoLink($image, $params);
    }

    /**
     * @param array $row
     * @return string
     */
    protected function getTextLink(array $row)
    {
        $label = $this->getLabel($row);
        $params = $this->getTypolinkParams($row);
        return $this->cObj->getTypoLink($label, $params);
    }

    /**
     * @param array $row
     * @return string
     */
    protected function getTypolinkParams(array $row)
    {
        $params = '';
        switch($row['link_type']) {
            case 1:
                $params = $row['link_page'];
                break;
            case 2:
                if($this->getForceDownload($row)) {
                    $conf=array();
                    $conf['useCacheHash'] = 1;
                    $conf['no_cache'] = 0;
                    $conf['parameter'] = $GLOBALS['TSFE']->page['uid'];
                    $conf['additionalParams'] = t3lib_div::implodeArrayForUrl('', array('tx_filelinks_pi1'=>array('download'=>$row['uid'],'cid'=>$this->cid)), '', true);
                    $params = $GLOBALS['TSFE']->cObj->typoLink_URL($conf);
                } else {
                    $params = $row['link_file'];
                }
                break;
            case 3:
                $params = $row['link_url'];
                break;
            case 4:
                $params = $row['link_mail'];
                break;
        }
        return $params;
    }

    /**
     * @param array $row
     * @return boolean
     */
    protected function getForceDownload(array $row)
    {
        $secure = $this->secure;
        $forcedl = $this->forcedl;

        if((int)$row['secure']>-1) {
            $secure = (bool)$row['secure'];
        }

        if((int)$row['forcedl']>-1) {
            $forcedl = (bool)$row['forcedl'];
        }

        return $secure || $forcedl;
    }

    /**
     * @param array $row
     * @return boolean
     */
    protected function showFileinfo(array $row)
    {
        $fileinfo = $this->fileinfo;
        if((int)$row['fileinfo']>-1) {
            $fileinfo = (bool)$row['fileinfo'];
        }
        return $fileinfo;
    }
    
    /**
     * @param array $row
     * @return string
     */
    protected function getLabel(array $row)
    {
        if(!empty($row['label'])) {
            return $row['label'];
        }
        if($row['link_type']==2) {
            $filename = urldecode(basename($row['link_file']));
            return str_replace('_', ' ', $filename);
        }
        return '';
    }

    /**
     * @param array $row
     * @return string 
     */
    protected function getCssClassName(array $row)
    {
        $class = 'filelink';

        switch($row['link_type']) {
            case 1:
                $class .= ' filelink-page';
                break;
            case 2:
                $class .= ' filelink-file';
                break;
            case 3:
                $class .= ' filelink-url';
                break;
            case 4:
                $class .= ' filelink-mail';
                break;
        }

        $thumbnail = $this->getThumbnail($row);
        if(empty($thumbnail)) {
            $class .= ' filelink-icon';
        } else {
            $class .= ' filelink-image';
        }

        if($this->firstId == $row['uid']) {
            $class .= ' filelink-first';
        }
        if($this->lastId == $row['uid']) {
            $class .= ' filelink-last';
        }

        return $class;
    }

    /**
     * @param array $row
     * @return string
     */
    protected function getThumbnail(array $row)
    {
        $filepath = $this->uploadFolder . $row['thumb'];
        if(is_file($filepath)) {
            return $filepath;
        }
        return '';
    }

    /**
     * @param array $row
     * @return string
     */
    protected function getIcon(array $row)
    {
        switch($row['link_type']) {
            case 1:
                $extension .= 'htm';
                break;
            case 2:
                // file
                $extension .= $this->getExtension($row['link_file']);
                break;
            case 3:
                $extension .= 'htm';
                break;
            case 4:
                $extension .= 'eml';
                break;
        }
        
        foreach(array('.png', '.gif', '.jpg') AS $type) {
            $icon = $this->iconPath . $extension . $type;
            if(is_file($icon)) {
                return $icon;
            }
        }

        return $this->iconPath . 'file.png';
    }

    /**
     * @param string $filepath
     * @return string
     */
    protected function getExtension($filepath)
    {
        $info = pathinfo($filepath);
        return $info['extension'];
    }

    /**
     * @return integer
     */
    private function getLocalizedUid()
    {
		return empty($this->cObj->data['_LOCALIZED_UID']) ? (int)$this->cObj->data['uid'] : (int)$this->cObj->data['_LOCALIZED_UID'];
    }

}


if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/filelinks/pi1/class.tx_filelinks_pi1.php'])	{
    include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/filelinks/pi1/class.tx_filelinks_pi1.php']);
}
